/**
 * dbmanager.c
 * Implementasi untuk modul dbmanager
 * Modul system berfungsi untuk memproses semua query yang berhubungan dengan tabel di database
 * Seperti: retrieve, insert, update, delete
 * Fri, 4 Dec 2009
 * By Kristanto 13208071
 * */


#include "../dbmanager/dbmanager.h"
#include "../graphmanager/graphmanager.h"

//KONSTRUKTOR
void CreateEmptyStudents(TStudent *student) {
	//KAMUS LOKAL
	
	//ALGORITMA
	student->NIM = CharToString("");
	student->Nama = CharToString("");
	student->KotaAsal = CharToString("");
	student->TglLahir = ParseDate(CharToString("00-00-1990"));
	student->IPK=0;
	student->JumlahSKS=0;
	student->Node = CharToString("");
}

void CreateEmptyTabStudents(TTabstudents *tabStudents) {
	//KAMUS LOKAL
	
	//ALGORITMA
	tabStudents->NStudents = 0;
}

void CreateEmptyLectures(TLecture *lecture) {
	//KAMUS LOKAL
	
	//ALGORITMA
	lecture->Kode = CharToString("");
	lecture->Nama = CharToString("");
	lecture->Bidang = CharToString("");
	lecture->SKS=0;
	lecture->Node = CharToString("");
}

void CreateEmptyTabLectures(TTablectures *tabLectures) {
	//KAMUS LOKAL
	
	//ALGORITMA
	tabLectures->NLectures = 0;
}

void CreateEmptyRelation(TLectures_Students *relation) {
	//KAMUS LOKAL
	
	//ALGORITMA
	relation->Kode = CharToString("");
	relation->NIM = CharToString("");
	relation->Semester=0;
	relation->Nilai=0;
	relation->ThnAkademik.Start=0;
	relation->ThnAkademik.End=0;
	relation->Node = CharToString("");
}

void CreateEmptyTabRelation(TTablectures_students *tabRelation) {
	//KAMUS LOKAL
	
	//ALGORITMA
	tabRelation->NRelation = 0;
}

TStudent CreateStudent(string NIM , string Nama , Date TglLahir , string KotaAsal , float IPK , int JumlahSKS) {
	//KAMUS LOKAL
	TStudent retval;
	
	//ALGORITMA
	retval.NIM = NIM;
	retval.Nama = Nama;
	retval.TglLahir = TglLahir;
	retval.KotaAsal = KotaAsal;
	retval.IPK = IPK;
	retval.JumlahSKS = JumlahSKS;
	return retval;
}

TLecture CreateLecture(string Kode , string Nama , int SKS , string Bidang) {
	//KAMUS LOKAL
	TLecture retval;
	
	//ALGORITMA
	retval.Kode = Kode;
	retval.Nama = Nama;
	retval.SKS = SKS;
	retval.Bidang = Bidang;
	return retval;
}

TLectures_Students CreateRelation(string NIM , string Kode , int Semester , TAcademicYear ThnAkademik , char Nilai) {
	//KAMUS LOKAL
	TLectures_Students retval;
	
	//ALGORITMA
	retval.NIM = NIM;
	retval.Kode = Kode;
	retval.Semester = Semester;
	retval.ThnAkademik = ThnAkademik;
	retval.Nilai = Nilai;
	return retval;
}

void InsertStudentsRow(TTabstudents *tabStudents , TStudent student) {
	//KAMUS LOKAL
	
	//ALGORITMA : Menambah jumlah Mahasiswa dalam Tabel Mahasiswa kemudian memasukkan data ke urutan terakhir
	tabStudents->NStudents++;
	tabStudents->t[tabStudents->NStudents]=student;
}

void InsertLecturesRow(TTablectures *tabLectures , TLecture lecture) {
	//KAMUS LOKAL
	
	//ALGORITMA : Menambah jumlah Matakuliah dalam Tabel Matakuliah kemudian memasukkan data ke urutan terakhir
	tabLectures->NLectures++;
	tabLectures->t[tabLectures->NLectures]=lecture;
}

void InsertLectures_StudentsRow(TTablectures_students *tabLectures_Students , TLectures_Students lecture_student) {
	//KAMUS LOKAL
	
	//ALGORITMA : Menambah jumlah PengambilanMK dalam Tabel PengambilanMK kemudian memasukkan data ke urutan terakhir
	tabLectures_Students->NRelation++;
	tabLectures_Students->t[tabLectures_Students->NRelation]=lecture_student;
}

//I-O
void PrintStudentInfo(TStudent student) {
	//KAMUS LOKAL
	string TglLahir = DateToString(student.TglLahir);
	
	//ALGORITMA 
	printf("%s %s %s %s %f %d\n" , student.NIM.s , student.Nama.s , TglLahir.s , student.KotaAsal.s , student.IPK , student.JumlahSKS);
}

void PrintLectureInfo(TLecture lecture) {
	//KAMUS LOKAL
	
	//ALGORITMA
	printf("%s %s %d %s\n" , lecture.Kode.s , lecture.Nama.s , lecture.SKS , lecture.Bidang.s);
}

void PrintRelationInfo(TLectures_Students relation) {
	//KAMUS LOKAL
	
	//ALGORITMA
	printf("%s %s %d %d-%d %c\n" , relation.NIM.s , relation.Kode.s , relation.Semester , relation.ThnAkademik.Start , relation.ThnAkademik.End , relation.Nilai);
}

//QUERY HANDLER
TTabstudents MergeTabStudent(TNodeList *NodeList) {
	//KAMUS LOKAL
	TTabstudents TempTable;
	int i = 0 , j = 0;
	
	//ALGORITMA : Membuat Tabel Mahasiswa kosong dan mengisinya dengan data-data Mahasiswa gabungan dari jaringan
	CreateEmptyTabStudents(&TempTable);
	forup(i , 1 , NodeList->NNode) {
		if(NodeList->node[i].IsStudentsExists) {
			forup(j , 1 , NodeList->node[i].students.NStudents) {
				if(!SearchStudent(&TempTable , NodeList->node[i].students.t[j].NIM)) {
					InsertStudentsRow(&TempTable , NodeList->node[i].students.t[j]);
				}
			}
		}
	}
	return TempTable;
}

TTablectures MergeTabLecture(TNodeList *NodeList) {
	//KAMUS LOKAL
	TTablectures TempTable;
	int i = 0 , j = 0;
	
	//ALGORITMA : Membuat Tabel Matakuliah kosong dan mengisinya dengan data-data Matakuliah gabungan dari jaringan
	CreateEmptyTabLectures(&TempTable);
	forup(i , 1 , NodeList->NNode) {
		if(NodeList->node[i].IsLecturesExists) {	
			forup(j , 1 , NodeList->node[i].lectures.NLectures) {
				if(!SearchLecture(&TempTable , NodeList->node[i].lectures.t[j].Kode)) {
					InsertLecturesRow(&TempTable , NodeList->node[i].lectures.t[j]);
				}
			}
		}
	}
	return TempTable;
}

TTablectures_students MergeTabRelation(TNodeList *NodeList) {
	//KAMUS LOKAL
	TTablectures_students TempTable;
	int i = 0 , j = 0;
	
	//ALGORITMA : Membuat Tabel PengambilanMK kosong dan mengisinya dengan data-data PengambilanMK gabungan dari jaringan
	CreateEmptyTabRelation(&TempTable);
	forup(i , 1 , NodeList->NNode) {
		if(NodeList->node[i].IsLectures_StudentsExists) {
			forup(j , 1 , NodeList->node[i].lectures_students.NRelation) {
				if(!SearchRelation(&TempTable 
				, NodeList->node[i].lectures_students.t[j].NIM
				, NodeList->node[i].lectures_students.t[j].Kode)) {
					InsertLectures_StudentsRow(&TempTable , NodeList->node[i].lectures_students.t[j]);
				}
			}
		}
	}
	return TempTable;
}


void RetrieveStudentsRecord(TAdjMatrix *m , TNodeList *NodeList , string ColumnName[10] , int NColumn , string Condition[21] , int ncond , boolean IsDetail , TNode Asal) {
	//KAMUS LOKAL
	TTabstudents TempTable = retrieveStudentsRecord(m , NodeList , ColumnName , NColumn , Condition , ncond , IsDetail , Asal);
	int i;
	TRetvalDijkstra x;
	
	//ALGORITMA : Membuat Tabel Mahasiswa sementara yang merupakan gabungan dari tabel-tabel dalam jaringan
	//kemudian menampilkannya satu per satu sesuai dengan permintaan pengguna
	if(SearchColumn(ColumnName , NColumn , "NIM")||IsStringEqual(ColumnName[1] , CharToString("*"))) printf("NIM         ");
	if(SearchColumn(ColumnName , NColumn , "Nama")||IsStringEqual(ColumnName[1] , CharToString("*"))) printf("Nama                   ");
	if(SearchColumn(ColumnName , NColumn , "TglLahir")||IsStringEqual(ColumnName[1] , CharToString("*"))) printf("TglLahir      ");
	if(SearchColumn(ColumnName , NColumn , "KotaAsal")||IsStringEqual(ColumnName[1] , CharToString("*"))) printf("KotaAsal      ");
	if(SearchColumn(ColumnName , NColumn , "IPK")||IsStringEqual(ColumnName[1] , CharToString("*"))) printf("IPK   ");
	if(SearchColumn(ColumnName , NColumn , "JumlahSKS")||IsStringEqual(ColumnName[1] , CharToString("*"))) printf("JumlahSKS  ");
	if(IsDetail) printf("Lokasi      Waktu Download    Jalur yang Digunakan ");
	printf("\n");
	float TotalCost=0;
	forup(i , 1 , TempTable.NStudents) {
		if(SearchColumn(ColumnName , NColumn , "NIM")||IsStringEqual(ColumnName[1] , CharToString("*"))) printf("%-11.11s " , TempTable.t[i].NIM.s);
		if(SearchColumn(ColumnName , NColumn , "Nama")||IsStringEqual(ColumnName[1] , CharToString("*"))) printf("%-22.22s " , TempTable.t[i].Nama.s);
		string Date = DateToString(TempTable.t[i].TglLahir);
		if(SearchColumn(ColumnName , NColumn , "TglLahir")||IsStringEqual(ColumnName[1] , CharToString("*"))) printf("%-13.13s " , Date.s);
		if(SearchColumn(ColumnName , NColumn , "KotaAsal")||IsStringEqual(ColumnName[1] , CharToString("*"))) printf("%-13.13s " , TempTable.t[i].KotaAsal.s);
		if(SearchColumn(ColumnName , NColumn , "IPK")||IsStringEqual(ColumnName[1] , CharToString("*"))) {
			if(TempTable.t[i].JumlahSKS!=null) printf("%0.3f " , TempTable.t[i].IPK);
			else printf("-     ");
		}
		if(SearchColumn(ColumnName , NColumn , "JumlahSKS")||IsStringEqual(ColumnName[1] , CharToString("*"))) {
			if(TempTable.t[i].JumlahSKS!=null) printf("%*d  " , 9 , TempTable.t[i].JumlahSKS);
			else printf("        -  ");
		}
		if(IsDetail) {
			x = FindPath(*m , NodeList->node[GetPhysicalNodeName(NodeList , TempTable.t[i].Node)].CPUTime , NodeList->NNode , GetPhysicalNodeName(NodeList , Asal.Name) , GetPhysicalNodeName(NodeList , TempTable.t[i].Node) , GetSizeStudent(TempTable.t[i]));
			printf("%-11.11s %.4f            " , TempTable.t[i].Node.s , x.Cost);
			PrintPath(x , NodeList);
			TotalCost+=x.Cost;
		}
		else printf("\n");
	}
	if(IsDetail) printf("Waktu total download = %.4f detik\n",TotalCost);
}

void RetrieveLecturesRecord(TAdjMatrix *m , TNodeList *NodeList , string ColumnName[10] , int NColumn , string Condition[21] , int ncond , boolean IsDetail , TNode Asal) {
	//KAMUS LOKAL
	TTablectures TempTable = retrieveLecturesRecord(m , NodeList , ColumnName , NColumn , Condition , ncond , IsDetail , Asal);
	int i;
	TRetvalDijkstra x;
	
	//ALGORITMA : Membuat Tabel Matakuliah sementara yang merupakan gabungan dari tabel-tabel dalam jaringan
	//kemudian menampilkannya satu per satu sesuai dengan permintaan pengguna
	if(SearchColumn(ColumnName , NColumn , "Kode")||IsStringEqual(ColumnName[1] , CharToString("*"))) printf("Kode    ");
	if(SearchColumn(ColumnName , NColumn , "Nama")||IsStringEqual(ColumnName[1] , CharToString("*"))) printf("Nama                                ");
	if(SearchColumn(ColumnName , NColumn , "SKS")||IsStringEqual(ColumnName[1] , CharToString("*"))) printf("SKS ");
	if(SearchColumn(ColumnName , NColumn , "Bidang")||IsStringEqual(ColumnName[1] , CharToString("*"))) printf("Bidang        ");
	if(IsDetail) printf("Lokasi      Waktu Download    Jalur yang Digunakan ");
	printf("\n");
	float TotalCost=0;
	forup(i , 1 , TempTable.NLectures) {
		if(SearchColumn(ColumnName , NColumn , "Kode")||IsStringEqual(ColumnName[1] , CharToString("*"))) printf("%-7.7s " , TempTable.t[i].Kode.s);
		if(SearchColumn(ColumnName , NColumn , "Nama")||IsStringEqual(ColumnName[1] , CharToString("*"))) printf("%-35.35s " , TempTable.t[i].Nama.s);
		if(SearchColumn(ColumnName , NColumn , "SKS")||IsStringEqual(ColumnName[1] , CharToString("*"))) printf("%*d " , 3 , TempTable.t[i].SKS);
		if(SearchColumn(ColumnName , NColumn , "Bidang")||IsStringEqual(ColumnName[1] , CharToString("*"))) printf("%-13.13s " , TempTable.t[i].Bidang.s);
		if(IsDetail) {
			x = FindPath(*m , NodeList->node[GetPhysicalNodeName(NodeList , TempTable.t[i].Node)].CPUTime , NodeList->NNode , GetPhysicalNodeName(NodeList , Asal.Name) , GetPhysicalNodeName(NodeList , TempTable.t[i].Node) , GetSizeLecture(TempTable.t[i]));
			printf("%-11.11s %.4f            " , TempTable.t[i].Node.s , x.Cost);
			PrintPath(x , NodeList);
			TotalCost+=x.Cost;
		}
		else printf("\n");
	}
	if(IsDetail) printf("Waktu total download = %.4f detik\n",TotalCost);
}

void RetrieveLectures_StudentsRecord(TAdjMatrix *m , TNodeList *NodeList , string ColumnName[10] , int NColumn , string Condition[21] , int ncond , boolean IsDetail , TNode Asal) {
	//KAMUS LOKAL
	TTablectures_students TempTable = retrieveLectures_StudentsRecord(m , NodeList , ColumnName , NColumn , Condition , ncond , IsDetail , Asal);
	int i;
	TRetvalDijkstra x;
	
	//ALGORITMA : Membuat Tabel PengambilanMK sementara yang merupakan gabungan dari tabel-tabel dalam jaringan
	//kemudian menampilkannya satu per satu sesuai dengan permintaan pengguna
	if(SearchColumn(ColumnName , NColumn , "NIM")||IsStringEqual(ColumnName[1] , CharToString("*"))) printf("NIM         ");
	if(SearchColumn(ColumnName , NColumn , "Kode")||IsStringEqual(ColumnName[1] , CharToString("*"))) printf("Kode    ");
	if(SearchColumn(ColumnName , NColumn , "Semester")||IsStringEqual(ColumnName[1] , CharToString("*"))) printf("Semester ");
	if(SearchColumn(ColumnName , NColumn , "ThnAkademik")||IsStringEqual(ColumnName[1] , CharToString("*"))) printf("ThnAkademik ");
	if(SearchColumn(ColumnName , NColumn , "Nilai")||IsStringEqual(ColumnName[1] , CharToString("*"))) printf("Nilai ");
	if(IsDetail) printf("Lokasi      Waktu Download    Jalur yang Digunakan ");
	printf("\n");
	float TotalCost=0;
	forup(i , 1 , TempTable.NRelation) {
		if(SearchColumn(ColumnName , NColumn , "NIM")||IsStringEqual(ColumnName[1] , CharToString("*"))) printf("%-11.11s " , TempTable.t[i].NIM.s);
		if(SearchColumn(ColumnName , NColumn , "Kode")||IsStringEqual(ColumnName[1] , CharToString("*"))) printf("%-7.7s " , TempTable.t[i].Kode.s);
		if(SearchColumn(ColumnName , NColumn , "Semester")||IsStringEqual(ColumnName[1] , CharToString("*"))) printf("%*d " , 8 , TempTable.t[i].Semester);
		if(SearchColumn(ColumnName , NColumn , "ThnAkademik")||IsStringEqual(ColumnName[1] , CharToString("*"))) printf("%d-%d   " , TempTable.t[i].ThnAkademik.Start , TempTable.t[i].ThnAkademik.End);
		if(SearchColumn(ColumnName , NColumn , "Nilai")||IsStringEqual(ColumnName[1] , CharToString("*"))) printf("    %c " , TempTable.t[i].Nilai);
		if(IsDetail) {
			x = FindPath(*m , NodeList->node[GetPhysicalNodeName(NodeList , TempTable.t[i].Node)].CPUTime , NodeList->NNode , GetPhysicalNodeName(NodeList , Asal.Name) , GetPhysicalNodeName(NodeList , TempTable.t[i].Node) , GetSizeLecture_Student(TempTable.t[i]));
            printf("%-11.11s %.4f            " , TempTable.t[i].Node.s , x.Cost);
            PrintPath(x , NodeList);
			TotalCost+=x.Cost;
		}
		else printf("\n");
	}
	if(IsDetail) printf("Waktu total download = %.4f detik\n",TotalCost);
}

TTabstudents retrieveStudentsRecord(TAdjMatrix *m , TNodeList *NodeList , string ColumnName[10] , int NColumn , string Condition[21] , int ncond , boolean IsDetail , TNode Asal) {
	//KAMUS LOKAL
	TTabstudents TempTable;
	float Cost[MaxStudents];
	int i = 0 , node;
	TRetvalDijkstra x;
	
	//ALGORITMA : Membuat Tabel Mahasiswa sementara yang merupakan gabungan dari tabel-tabel dalam jaringan dengan kondisi tertentu
	CreateEmptyTabStudents(&TempTable);
	forup(i , 1 , NodeList->NNode) {
		if(NodeList->node[i].IsStudentsExists) {
			int j = 0;
			forup(j , 1 , NodeList->node[i].students.NStudents) {
				x = FindPath(*m , NodeList->node[GetPhysicalNodeName(NodeList , NodeList->node[i].Name)].CPUTime , NodeList->NNode , GetPhysicalNodeName(NodeList , Asal.Name) , GetPhysicalNodeName(NodeList , NodeList->node[i].Name) , GetSizeStudent(NodeList->node[i].students.t[j]));
				if((x.PathLength != 0) && (isStudentRowValid(Condition , ncond , NodeList->node[i].students.t[j])||IsStringEqual(Condition[0] , CharToString("-")))) {
					node = SearchStudent(&TempTable , NodeList->node[i].students.t[j].NIM);
					
					if (node != 0) {
						if (x.Cost < Cost[node]) {
							TempTable.t[node].Node = NodeList->node[i].Name;
							Cost[node] = x.Cost;
						}
					}
					else {
						InsertStudentsRow(&TempTable , NodeList->node[i].students.t[j]);
						TempTable.t[TempTable.NStudents].Node=NodeList->node[i].Name;
						Cost[TempTable.NStudents] = x.Cost;
					}
				}
			}
		}
	}
	return TempTable;
}

TTablectures retrieveLecturesRecord(TAdjMatrix *m , TNodeList *NodeList , string ColumnName[10] , int NColumn , string Condition[21] , int ncond , boolean IsDetail , TNode Asal) {
	//KAMUS LOKAL
	TTablectures TempTable;
	float Cost[MaxLectures];
	int i = 0 , node;
	TRetvalDijkstra x;
	
	//ALGORITMA : Membuat Tabel Matakuliah sementara yang merupakan gabungan dari tabel-tabel dalam jaringan dengan kondisi tertentu
	CreateEmptyTabLectures(&TempTable);
	forup(i , 1 , NodeList->NNode) {
		if(NodeList->node[i].IsLecturesExists) {
			int j = 0;
			forup(j , 1 , NodeList->node[i].lectures.NLectures) {
				x = FindPath(*m , NodeList->node[GetPhysicalNodeName(NodeList , NodeList->node[i].Name)].CPUTime , NodeList->NNode , GetPhysicalNodeName(NodeList , Asal.Name) , GetPhysicalNodeName(NodeList , NodeList->node[i].Name) , GetSizeLecture(NodeList->node[i].lectures.t[j]));
				if((x.PathLength != 0) && (isLectureRowValid(Condition , ncond , NodeList->node[i].lectures.t[j])||IsStringEqual(Condition[0] , CharToString("-")))) {
					node = SearchLecture(&TempTable , NodeList->node[i].lectures.t[j].Kode);
					if (node != 0) {
						if (x.Cost < Cost[node]) {
							TempTable.t[node].Node = NodeList->node[i].Name;
							Cost[node] = x.Cost;
						}
					}
					else {
						InsertLecturesRow(&TempTable , NodeList->node[i].lectures.t[j]);
						TempTable.t[TempTable.NLectures].Node=NodeList->node[i].Name;
						Cost[TempTable.NLectures] = x.Cost;
					}
				}
			}
		}
	}
	return TempTable;
}

TTablectures_students retrieveLectures_StudentsRecord(TAdjMatrix *m , TNodeList *NodeList , string ColumnName[10] , int NColumn , string Condition[21] , int ncond , boolean IsDetail , TNode Asal) {
	//KAMUS LOKAL
	TTablectures_students TempTable;
	float Cost[MaxStudents * MaxTake];
	int i , node;
	TRetvalDijkstra x;
	
	//ALGORITMA : Membuat Tabel PengambilanMK sementara yang merupakan gabungan dari tabel-tabel dalam jaringan dengan kondisi tertentu
	CreateEmptyTabRelation(&TempTable);
	forup(i , 1 , NodeList->NNode) {
		if(NodeList->node[i].IsLectures_StudentsExists) {
			int j;
			forup(j , 1 , NodeList->node[i].lectures_students.NRelation) {
				x = FindPath(*m , NodeList->node[GetPhysicalNodeName(NodeList , NodeList->node[i].Name)].CPUTime , NodeList->NNode , GetPhysicalNodeName(NodeList , Asal.Name) , GetPhysicalNodeName(NodeList , NodeList->node[i].Name) , GetSizeLecture_Student(NodeList->node[i].lectures_students.t[j]));
				if((x.PathLength != 0) && (isLecture_StudentRowValid(Condition , ncond , NodeList->node[i].lectures_students.t[j])||IsStringEqual(Condition[0] , CharToString("-")))) {
					node = SearchRelation(&TempTable 
						, NodeList->node[i].lectures_students.t[j].NIM
						, NodeList->node[i].lectures_students.t[j].Kode);
						
					if (node != 0) {
						if (x.Cost < Cost[node]) {
							TempTable.t[node].Node = NodeList->node[i].Name;
							Cost[node] = x.Cost;
						}
					}
					else {
						InsertLectures_StudentsRow(&TempTable , NodeList->node[i].lectures_students.t[j]);
						TempTable.t[TempTable.NRelation].Node=NodeList->node[i].Name;
						Cost[TempTable.NRelation] = x.Cost;
					}
				}
			}
		}
	}
	return TempTable;
}

void InsertStudentsRecord(TAdjMatrix *m , TNode *node , TNodeList *NodeList , TStudent student , TNode Asal) {
	//KAMUS LOKAL
	TRetvalDijkstra x;
	
	//ALGORITMA : Mengisi Node yang ditentukan dengan data Mahasiswa jika ada jalur dari Node asal ke Node yang bersangkutan dan sesuai kondisi
	x = FindPath(*m , node->CPUTime , NodeList->NNode , GetPhysicalNodeName(NodeList , Asal.Name) , GetPhysicalNodeName(NodeList , node->Name) , GetSizeStudent(student));
	if (x.PathLength != 0) {
		if(!SearchStudent(&node->students , student.NIM)) {
			InsertStudentsRow(&node->students , student);
			printf("Lokasi insert : %s\n" , node->Name.s);
			printf("Jalur yang digunakan : ");PrintPath(x , NodeList);
			printf("Insert data ke lokasi %s sukses.\n" , node->Name.s);
			printf("Waktu total upload : %.4f\n" , x.Cost);
		}
		else {
			printf("Data mahasiswa sudah ada.\n");
		}
	}
	else
		SetError(11);
}

void InsertLecturesRecord(TAdjMatrix *m , TNode *node , TNodeList *NodeList , TLecture lecture , TNode Asal) {
	//KAMUS LOKAL
	TRetvalDijkstra x;
	
	//ALGORITMA : Mengisi Node yang ditentukan dengan data Matakuliah jika ada jalur dari Node asal ke Node yang bersangkutan dan sesuai kondisi
	x = FindPath(*m , node->CPUTime , NodeList->NNode , GetPhysicalNodeName(NodeList , Asal.Name) , GetPhysicalNodeName(NodeList , node->Name) , GetSizeLecture (lecture));
	if (x.PathLength != 0) {
		if (!SearchLecture(&node->lectures , lecture.Kode)) {
			InsertLecturesRow(&node->lectures , lecture);
			printf("Lokasi insert : %s\n" , node->Name.s);
			printf("Jalur yang digunakan : ");PrintPath(x , NodeList);
			printf("Insert data ke lokasi %s sukses.\n" , node->Name.s);
			printf("Waktu total upload : %.4f\n" , x.Cost);
		}
		else {
			printf("Data matakuliah sudah ada.\n");
		}
	}
	else
		SetError(11);
}

void InsertLectures_StudentsRecord(TAdjMatrix *m , TNode *node , TNodeList *NodeList , TLectures_Students relation , TNode Asal) {
	//KAMUS LOKAL
	TRetvalDijkstra x;
	
	//ALGORITMA : Mengisi Node yang ditentukan dengan data PengambilanMK jika ada jalur dari Node asal ke Node yang bersangkutan dan sesuai kondisi
	x = FindPath(*m , node->CPUTime , NodeList->NNode , GetPhysicalNodeName(NodeList , Asal.Name) , GetPhysicalNodeName(NodeList , node->Name) , GetSizeLecture_Student (relation));
	if (x.PathLength != 0) {
		if (!SearchRelation(&node->lectures_students , relation.NIM , relation.Kode)) {
			InsertLectures_StudentsRow(&node->lectures_students , relation);
			printf("Lokasi insert : %s\n" , node->Name.s);
			printf("Jalur yang digunakan : ");PrintPath(x , NodeList);
			printf("Insert data ke lokasi %s sukses.\n" , node->Name.s);
			printf("Waktu total upload : %.4f\n" , x.Cost);
		}
		else {
			printf("Data pengambilanmk sudah ada.\n");
		}
	}
	else
		SetError(11);
}

void UpdateStudentsTable(TAdjMatrix *m , TNodeList *NodeList , TStudent student , string Condition[21] , int ncond , TNode Asal) {
	//KAMUS LOKAL
	int i , n = 0;
	float TotalCost = 0;
	TRetvalDijkstra x;
	
	//ALGORITMA : Memeriksa semua data Mahasiswa dari setiap Node yang terhubung dengan Node asal,
	//jika sama dengan kondisi, maka data diubah sesuai dengan data dari pengguna dan menampilkan waktu total proses
	forup(i , 1 , NodeList->NNode) {
		if(NodeList->node[i].IsStudentsExists) {
			int j;
			x = FindPath(*m , NodeList->node[GetPhysicalNodeName(NodeList , NodeList->node[i].Name)].CPUTime , NodeList->NNode , GetPhysicalNodeName(NodeList , Asal.Name) , GetPhysicalNodeName(NodeList , NodeList->node[i].Name) , GetSizeStudent(NodeList->node[i].students.t[i]));
			if(x.PathLength != 0) {
				forup(j , 1 , NodeList->node[i].students.NStudents) {
					if(isStudentRowValid(Condition , ncond , NodeList->node[i].students.t[j])||IsStringEqual(Condition[0] , CharToString("-"))) {
						if(!IsStringEqual(student.NIM , CharToString("-"))) NodeList->node[i].students.t[j].NIM=student.NIM;
						if(!IsStringEqual(student.Nama , CharToString("-"))) NodeList->node[i].students.t[j].Nama=student.Nama;
						if(!IsDateEqual(student.TglLahir , ParseDate(CharToString("00-00-0000")))) NodeList->node[i].students.t[j].TglLahir=student.TglLahir;
						if(!IsStringEqual(student.KotaAsal , CharToString("-"))) NodeList->node[i].students.t[j].KotaAsal=student.KotaAsal;
						if(student.IPK!=null) NodeList->node[i].students.t[j].IPK=student.IPK;
						if(student.JumlahSKS!=null) NodeList->node[i].students.t[j].JumlahSKS=student.JumlahSKS;
						TotalCost+=NodeList->node[i].CPUTime;
						n++;
					}
				}
			}
		}
	}
	printf("Update %d record sukses.\n" , n);
	printf("Waktu total proses = %.4f detik\n" , TotalCost);
}

void UpdateLecturesTable(TAdjMatrix *m , TNodeList *NodeList , TLecture lecture , string Condition[21] , int ncond , TNode Asal) {
	//KAMUS LOKAL
	int i , n = 0;
	float TotalCost = 0;
	TRetvalDijkstra x;
	
	//ALGORITMA : Memeriksa semua data Matakuliah dari setiap Node yang terhubung dengan Node asal,
	//jika sama dengan kondisi, maka data diubah sesuai dengan data dari pengguna dan menampilkan waktu total proses
	forup(i , 1 , NodeList->NNode) {
		if(NodeList->node[i].IsLecturesExists) {
			int j;
			x = FindPath(*m , NodeList->node[GetPhysicalNodeName(NodeList , NodeList->node[i].Name)].CPUTime , NodeList->NNode , GetPhysicalNodeName(NodeList , Asal.Name) , GetPhysicalNodeName(NodeList , NodeList->node[i].Name) , GetSizeLecture(NodeList->node[i].lectures.t[i]));
			if(x.PathLength != 0) {
				forup(j , 1 , NodeList->node[i].lectures.NLectures) {
					if(isLectureRowValid(Condition , ncond , NodeList->node[i].lectures.t[j])||IsStringEqual(Condition[0] , CharToString("-"))) {
						if(!IsStringEqual(lecture.Kode , CharToString("-"))) NodeList->node[i].lectures.t[j].Kode=lecture.Kode;
						if(!IsStringEqual(lecture.Nama , CharToString("-"))) NodeList->node[i].lectures.t[j].Nama=lecture.Nama;
						if(lecture.SKS!=null) NodeList->node[i].lectures.t[j].SKS=lecture.SKS;
						if(!IsStringEqual(lecture.Bidang , CharToString("-"))) NodeList->node[i].lectures.t[j].Bidang=lecture.Bidang;
						TotalCost+=NodeList->node[i].CPUTime;
						n++;
					}
				}
			}
		}
	}
	printf("Update %d record sukses.\n" , n);
	printf("Waktu total proses = %.4f detik\n" , TotalCost);
}

void UpdateLectures_StudentsTable(TAdjMatrix *m , TNodeList *NodeList , TLectures_Students relation , string Condition[21] , int ncond , TNode Asal) {
	//KAMUS LOKAL
	int i , n = 0;
	float TotalCost = 0;
	TRetvalDijkstra x;
	
	//ALGORITMA : Memeriksa semua data PengambilanMK dari setiap Node yang terhubung dengan Node asal,
	//jika sama dengan kondisi, maka data diubah sesuai dengan data dari pengguna dan menampilkan waktu total proses
	forup(i , 1 , NodeList->NNode) {
		if(NodeList->node[i].IsLectures_StudentsExists) {
			int j;
			x = FindPath(*m , NodeList->node[GetPhysicalNodeName(NodeList , NodeList->node[i].Name)].CPUTime , NodeList->NNode , GetPhysicalNodeName(NodeList , Asal.Name) , GetPhysicalNodeName(NodeList , NodeList->node[i].Name) , GetSizeLecture_Student(NodeList->node[i].lectures_students.t[i]));
			if(x.PathLength != 0) {
				forup(j , 1 , NodeList->node[i].lectures_students.NRelation) {
					if(isLecture_StudentRowValid(Condition , ncond , NodeList->node[i].lectures_students.t[j])||IsStringEqual(Condition[0] , CharToString("-"))) {
						if(!IsStringEqual(relation.NIM , CharToString("-"))) NodeList->node[i].lectures_students.t[j].NIM=relation.NIM;
						if(!IsStringEqual(relation.Kode , CharToString("-"))) NodeList->node[i].lectures_students.t[j].Kode=relation.Kode;
						if(!IsThnAkademikEqual(relation.ThnAkademik , StringToThnAkademik(CharToString("0000-0000")))) NodeList->node[i].lectures_students.t[j].ThnAkademik=relation.ThnAkademik;
						if(relation.Semester!=null) NodeList->node[i].lectures_students.t[j].Semester=relation.Semester;
						if(relation.Nilai!='-') NodeList->node[i].lectures_students.t[j].Nilai=relation.Nilai;
						TotalCost+=NodeList->node[i].CPUTime;
						n++;
					}
				}
			}
		}
	}
	printf("Update %d record sukses.\n" , n);
	printf("Waktu total proses = %.4f detik\n" , TotalCost);
}

void DeleteStudentsRecord(TAdjMatrix *m , TNodeList *NodeList , string Condition[21] , int ncond , TNode Asal) {
	//KAMUS LOKAL
	int i , j , k , n = 0;
	float TotalCost = 0;
	TRetvalDijkstra x;
	
	//ALGORITMA : Memeriksa semua data Mahasiswa dari setiap Node yang terhubung dengan Node asal,
	//jika sama dengan kondisi, maka data dihapus dan menampilkan waktu total proses
	forup(i , 1 , NodeList->NNode) {
		x = FindPath(*m , NodeList->node[GetPhysicalNodeName(NodeList , NodeList->node[i].Name)].CPUTime , NodeList->NNode , GetPhysicalNodeName(NodeList , Asal.Name) , GetPhysicalNodeName(NodeList , NodeList->node[i].Name) , GetSizeStudent(NodeList->node[i].students.t[i]));
		if((NodeList->node[i].IsStudentsExists) && (x.PathLength != 0)) {
			j=1;
			while (j <= NodeList->node[i].students.NStudents) {
				if(isStudentRowValid(Condition , ncond , NodeList->node[i].students.t[j])||IsStringEqual(Condition[0] , CharToString("-"))) {
					forup(k , j , NodeList->node[i].students.NStudents-1) {
						NodeList->node[i].students.t[k]=NodeList->node[i].students.t[k+1];
					}
					n++;
					TotalCost+=NodeList->node[i].CPUTime;
					CreateEmptyStudents(&NodeList->node[i].students.t[NodeList->node[i].students.NStudents]);
					NodeList->node[i].students.NStudents--;
				}
				else j++;
			}
		}
	}
	printf("Delete %d record sukses.\n" , n);
	printf("Waktu total proses = %.4f detik\n" , TotalCost);
}

void DeleteLecturesRecord(TAdjMatrix *m , TNodeList *NodeList , string Condition[21] , int ncond , TNode Asal) {
	//KAMUS LOKAL
	int i , n = 0;
	float TotalCost = 0;
	TRetvalDijkstra x;
	
	//ALGORITMA : Memeriksa semua data Matakuliah dari setiap Node yang terhubung dengan Node asal,
	//jika sama dengan kondisi, maka data dihapus dan menampilkan waktu total proses
	forup(i , 1 , NodeList->NNode) {
		x = FindPath(*m , NodeList->node[GetPhysicalNodeName(NodeList , NodeList->node[i].Name)].CPUTime , NodeList->NNode , GetPhysicalNodeName(NodeList , Asal.Name) , GetPhysicalNodeName(NodeList , NodeList->node[i].Name) , GetSizeLecture(NodeList->node[i].lectures.t[i]));
		if((NodeList->node[i].IsLecturesExists) && (x.PathLength != 0)) {
			int j=1;
			while (j <= NodeList->node[i].lectures.NLectures) {
				if(isLectureRowValid(Condition , ncond , NodeList->node[i].lectures.t[j])||IsStringEqual(Condition[0] , CharToString("-"))) {
					int k;
					forup(k , j , NodeList->node[i].lectures.NLectures-1) {
						NodeList->node[i].lectures.t[k]=NodeList->node[i].lectures.t[k+1];
					}
					n++;
					TotalCost+=NodeList->node[i].CPUTime;
					CreateEmptyLectures(&NodeList->node[i].lectures.t[NodeList->node[i].lectures.NLectures]);
					NodeList->node[i].lectures.NLectures--;
				}
				else j++;
			}
		}
	}
	printf("Delete %d record sukses.\n" , n);
	printf("Waktu total proses = %.4f detik\n" , TotalCost);
}

void DeleteLectures_StudentsRecord(TAdjMatrix *m , TNodeList *NodeList , string Condition[21] , int ncond , TNode Asal) {
	//KAMUS LOKAL
	int i , n = 0;
	float TotalCost = 0;
	TRetvalDijkstra x;
	
	//ALGORITMA : Memeriksa semua data PengambilanMK dari setiap Node yang terhubung dengan Node asal,
	//jika sama dengan kondisi, maka data dihapus dan menampilkan waktu total proses
	forup(i , 1 , NodeList->NNode) {
		x = FindPath(*m , NodeList->node[GetPhysicalNodeName(NodeList , NodeList->node[i].Name)].CPUTime , NodeList->NNode , GetPhysicalNodeName(NodeList , Asal.Name) , GetPhysicalNodeName(NodeList , NodeList->node[i].Name) , GetSizeLecture_Student(NodeList->node[i].lectures_students.t[i]));
		if((NodeList->node[i].IsLectures_StudentsExists) && (x.PathLength != 0)){
			int j=1;
			while (j <= NodeList->node[i].lectures_students.NRelation) {
				if(isLecture_StudentRowValid(Condition , ncond , NodeList->node[i].lectures_students.t[j])||IsStringEqual(Condition[0] , CharToString("-"))) {
					int k;
					forup(k , j , NodeList->node[i].lectures_students.NRelation-1) {
						NodeList->node[i].lectures_students.t[k]=NodeList->node[i].lectures_students.t[k+1];
					}
					n++;
					TotalCost+=NodeList->node[i].CPUTime;
					CreateEmptyRelation(&NodeList->node[i].lectures_students.t[NodeList->node[i].lectures_students.NRelation]);
					NodeList->node[i].lectures_students.NRelation--;
				}
				else j++;
			}
		}
	}
	printf("Delete %d record sukses.\n" , n);
	printf("Waktu total proses = %.4f detik\n" , TotalCost);
}

//PREDIKAT-PREDIKAT
int SearchStudent(TTabstudents *tabStudents , string NIM) {
	//KAMUS LOKAL
	int i;
	
	//ALGORITMA : mengecek setiap record Mahasiswa dari Tabel Mahasiswa,
	//mengembalikan posisinya jika NIM nya cocok dengan yang diminta
	forup(i , 1 , tabStudents->NStudents) {
		if(IsStringEqual(tabStudents->t[i].NIM , NIM)) return i;
	}
	return 0;
}

int SearchLecture(TTablectures *tabLectures , string Kode) {
	//KAMUS LOKAL
	int i;
	
	//ALGORITMA : mengecek setiap record Matakuliah dari Tabel Matakuliah,
	//mengembalikan posisinya jika Kode nya cocok dengan yang diminta
	forup(i , 1 , tabLectures->NLectures) {
		if(IsStringEqual(UpperCase(tabLectures->t[i].Kode) , UpperCase(Kode))) return i;
	}
	return 0;
}

int SearchRelation(TTablectures_students *tabLectures_Students , string NIM , string Kode) {
	//KAMUS LOKAL
	int i;
	
	//ALGORITMA : mengecek setiap record PengambilanMK dari Tabel PengambilanMK,
	//mengembalikan posisinya jika NIM dan Kode nya cocok dengan yang diminta
	forup(i , 1 , tabLectures_Students->NRelation) {
		if(IsStringEqual(tabLectures_Students->t[i].NIM , NIM)
		&& IsStringEqual(UpperCase(tabLectures_Students->t[i].Kode) , UpperCase(Kode))) return i;
	}
	return 0;
}

boolean IsOperator(string cond) {
	//KAMUS LOKAL
	
	//ALGORITMA : Mengembalikan true jika cond adalah salah satu dari operator
	return (IsStringEqual(cond , CharToString("="))
			|| IsStringEqual(cond , CharToString("<="))
			|| IsStringEqual(cond , CharToString(">="))
			|| IsStringEqual(cond , CharToString("<"))
			|| IsStringEqual(cond , CharToString(">"))
			|| IsStringEqual(cond , CharToString("!=")));
}

boolean SearchColumn(string ColumnName[10] , int NColumn , char *c) {
	//KAMUS LOKAL
	int i;
	
	//ALGORITMA : Mencari ColumnName yang sama dengan c,
	//jika ketemu, menghasilkan true, jika tidak, false
	forup(i , 1 , NColumn) {
		if(IsStringEqual(UpperCase(ColumnName[i]) , UpperCase(CharToString(c)))) return true;
	}
	return false;
}

boolean IsStudentRowValid(string Condition[3] , TStudent student) {
	//KAMUS LOKAL
	
	//ALGORITMA : Mengecek semua kemungkinan kondisi pada Mahasiswa,
	//jika sama, maka menghasilkan nilai true, jika tidak, false
	if(IsStringEqual(UpperCase(Condition[0]) , CharToString("NIM"))) {
		if(IsStringEqual(Condition[1] , CharToString("="))) return IsStringEqual(Condition[2] , student.NIM);
		else if(IsStringEqual(Condition[1] , CharToString("<="))) return IsStringEqual(Condition[2] , student.NIM)||IsStringLt(student.NIM , Condition[2]);
		else if(IsStringEqual(Condition[1] , CharToString(">="))) return IsStringEqual(Condition[2] , student.NIM)||IsStringLt(Condition[2] , student.NIM);
		else if(IsStringEqual(Condition[1] , CharToString("<"))) return IsStringLt(Condition[2] , student.NIM);
		else if(IsStringEqual(Condition[1] , CharToString(">"))) return !IsStringLt(Condition[2] , student.NIM);
		else if(IsStringEqual(Condition[1] , CharToString("!="))) return !IsStringEqual(Condition[2] , student.NIM);
	}
	else if(IsStringEqual(UpperCase(Condition[0]) , CharToString("NAMA"))) {
		if(IsStringEqual(Condition[1] , CharToString("="))) return IsStringEqual(UpperCase(Condition[2]) , UpperCase(student.Nama));
		else if(IsStringEqual(Condition[1] , CharToString("!="))) return !IsStringEqual(UpperCase(Condition[2]) , UpperCase(student.Nama));
	}
	else if(IsStringEqual(UpperCase(Condition[0]) , CharToString("TGLLAHIR"))) {
		if(IsStringEqual(Condition[1] , CharToString("="))) return IsDateEqual(ParseDate(Condition[2]) , student.TglLahir);
		else if(IsStringEqual(Condition[1] , CharToString("<="))) return IsDateEqual(ParseDate(Condition[2]) , student.TglLahir)||IsDateLt(student.TglLahir , ParseDate(Condition[2]));
		else if(IsStringEqual(Condition[1] , CharToString(">="))) return IsDateEqual(ParseDate(Condition[2]) , student.TglLahir)||IsDateLt(ParseDate(Condition[2]) , student.TglLahir);
		else if(IsStringEqual(Condition[1] , CharToString("<"))) return IsDateLt(ParseDate(Condition[2]) , student.TglLahir);
		else if(IsStringEqual(Condition[1] , CharToString(">"))) return !IsDateLt(ParseDate(Condition[2]) , student.TglLahir);
		else if(IsStringEqual(Condition[1] , CharToString("!="))) return !IsDateEqual(ParseDate(Condition[2]) , student.TglLahir);
	}
	else if(IsStringEqual(UpperCase(Condition[0]) , CharToString("KOTAASAL"))) {
		if(IsStringEqual(Condition[1] , CharToString("="))) return IsStringEqual(UpperCase(Condition[2]) , UpperCase(student.KotaAsal));
		else if(IsStringEqual(Condition[1] , CharToString("!="))) return !IsStringEqual(UpperCase(Condition[2]) , UpperCase(student.KotaAsal));
	}
	else if(IsStringEqual(UpperCase(Condition[0]) , CharToString("IPK"))) {
		if(IsStringEqual(Condition[1] , CharToString("="))) return student.IPK==StringToFloat(Condition[2]);
		else if(IsStringEqual(Condition[1] , CharToString("<="))) return (student.IPK<=StringToFloat(Condition[2])) && (student.IPK != -1);
		else if(IsStringEqual(Condition[1] , CharToString(">="))) return (student.IPK>=StringToFloat(Condition[2])) && (student.IPK != -1);
		else if(IsStringEqual(Condition[1] , CharToString("<"))) return (student.IPK<StringToFloat(Condition[2])) && (student.IPK != -1);
		else if(IsStringEqual(Condition[1] , CharToString(">"))) return (student.IPK>StringToFloat(Condition[2])) && (student.IPK != -1);
		else if(IsStringEqual(Condition[1] , CharToString("!="))) return student.IPK!=StringToFloat(Condition[2]);
	}
	else if(IsStringEqual(UpperCase(Condition[0]) , CharToString("JUMLAHSKS"))) {
		if(IsStringEqual(Condition[1] , CharToString("="))) return student.JumlahSKS==StringToFloat(Condition[2]);
		else if(IsStringEqual(Condition[1] , CharToString("<="))) return (student.JumlahSKS<=StringToFloat(Condition[2])) && (student.JumlahSKS != -1);
		else if(IsStringEqual(Condition[1] , CharToString(">="))) return (student.JumlahSKS>=StringToFloat(Condition[2])) && (student.JumlahSKS != -1);
		else if(IsStringEqual(Condition[1] , CharToString("<"))) return (student.JumlahSKS<StringToFloat(Condition[2])) && (student.JumlahSKS != -1);
		else if(IsStringEqual(Condition[1] , CharToString(">"))) return (student.JumlahSKS>StringToFloat(Condition[2])) && (student.JumlahSKS != -1);
		else if(IsStringEqual(Condition[1] , CharToString("!="))) return student.JumlahSKS!=StringToFloat(Condition[2]);
	}
}

boolean isStudentRowValid(string Condition[21] , int ncond , TStudent student) {
	//KAMUS LOKAL
	int i;
	int orpos = -1 , andpos = -1;
	string condLeft[21] , condRight[21];
	int ncondLeft = 0 , ncondRight = 0;
	
	//ALGORITMA : Mengecek semua kemungkinan kondisi pada Mahasiswa,
	//jika sama, maka menghasilkan nilai true, jika tidak, false
	if (ncond == 3 || ncond == 1) {
		if(IsStringEqual(UpperCase(Condition[0]) , CharToString("NIM"))) {
			if(IsStringEqual(Condition[1] , CharToString("="))) return IsStringEqual(Condition[2] , student.NIM);
			else if(IsStringEqual(Condition[1] , CharToString("<="))) return IsStringEqual(Condition[2] , student.NIM)||IsStringLt(student.NIM , Condition[2]);
			else if(IsStringEqual(Condition[1] , CharToString(">="))) return IsStringEqual(Condition[2] , student.NIM)||IsStringLt(Condition[2] , student.NIM);
			else if(IsStringEqual(Condition[1] , CharToString("<"))) return IsStringLt(Condition[2] , student.NIM);
			else if(IsStringEqual(Condition[1] , CharToString(">"))) return !IsStringLt(Condition[2] , student.NIM);
			else if(IsStringEqual(Condition[1] , CharToString("!="))) return !IsStringEqual(Condition[2] , student.NIM);
		} 
		else if(IsStringEqual(UpperCase(Condition[0]) , CharToString("NAMA"))) {
			if(IsStringEqual(Condition[1] , CharToString("="))) return IsStringEqual(UpperCase(Condition[2]) , UpperCase(student.Nama));
			else if(IsStringEqual(Condition[1] , CharToString("!="))) return !IsStringEqual(UpperCase(Condition[2]) , UpperCase(student.Nama));
		}
		else if(IsStringEqual(UpperCase(Condition[0]) , CharToString("TGLLAHIR"))) {
			if(IsStringEqual(Condition[1] , CharToString("="))) return IsDateEqual(ParseDate(Condition[2]) , student.TglLahir);
			else if(IsStringEqual(Condition[1] , CharToString("<="))) return IsDateEqual(ParseDate(Condition[2]) , student.TglLahir)||IsDateLt(student.TglLahir , ParseDate(Condition[2]));
			else if(IsStringEqual(Condition[1] , CharToString(">="))) return IsDateEqual(ParseDate(Condition[2]) , student.TglLahir)||IsDateLt(ParseDate(Condition[2]) , student.TglLahir);
			else if(IsStringEqual(Condition[1] , CharToString("<"))) return IsDateLt(ParseDate(Condition[2]) , student.TglLahir);
			else if(IsStringEqual(Condition[1] , CharToString(">"))) return !IsDateLt(ParseDate(Condition[2]) , student.TglLahir);
			else if(IsStringEqual(Condition[1] , CharToString("!="))) return !IsDateEqual(ParseDate(Condition[2]) , student.TglLahir);
		}
		else if(IsStringEqual(UpperCase(Condition[0]) , CharToString("KOTAASAL"))) {
			if(IsStringEqual(Condition[1] , CharToString("="))) return IsStringEqual(UpperCase(Condition[2]) , UpperCase(student.KotaAsal));
			else if(IsStringEqual(Condition[1] , CharToString("!="))) return !IsStringEqual(UpperCase(Condition[2]) , UpperCase(student.KotaAsal));
		}
		else if(IsStringEqual(UpperCase(Condition[0]) , CharToString("IPK"))) {
			if(IsStringEqual(Condition[1] , CharToString("="))) return student.IPK==StringToFloat(Condition[2]);
			else if(IsStringEqual(Condition[1] , CharToString("<="))) return (student.IPK<=StringToFloat(Condition[2])) && (student.IPK != -1);
			else if(IsStringEqual(Condition[1] , CharToString(">="))) return (student.IPK>=StringToFloat(Condition[2])) && (student.IPK != -1);
			else if(IsStringEqual(Condition[1] , CharToString("<"))) return (student.IPK<StringToFloat(Condition[2])) && (student.IPK != -1);
			else if(IsStringEqual(Condition[1] , CharToString(">"))) return (student.IPK>StringToFloat(Condition[2])) && (student.IPK != -1);
			else if(IsStringEqual(Condition[1] , CharToString("!="))) return student.IPK!=StringToFloat(Condition[2]);
		}
		else if(IsStringEqual(UpperCase(Condition[0]) , CharToString("JUMLAHSKS"))) {
			if(IsStringEqual(Condition[1] , CharToString("="))) return student.JumlahSKS==StringToFloat(Condition[2]);
			else if(IsStringEqual(Condition[1] , CharToString("<="))) return (student.JumlahSKS<=StringToFloat(Condition[2])) && (student.JumlahSKS != -1);
			else if(IsStringEqual(Condition[1] , CharToString(">="))) return (student.JumlahSKS>=StringToFloat(Condition[2])) && (student.JumlahSKS != -1);
			else if(IsStringEqual(Condition[1] , CharToString("<"))) return (student.JumlahSKS<StringToFloat(Condition[2])) && (student.JumlahSKS != -1);
			else if(IsStringEqual(Condition[1] , CharToString(">"))) return (student.JumlahSKS>StringToFloat(Condition[2])) && (student.JumlahSKS != -1);
			else if(IsStringEqual(Condition[1] , CharToString("!="))) return student.JumlahSKS!=StringToFloat(Condition[2]);
		}
	}
	else {
		orpos = -1;
		andpos = -1;
		ncondLeft = 0;
		ncondRight = 0;
		
		forup(i , 0 , ncond-1) {
			if((IsStringEqual(UpperCase(Condition[i]) , CharToString("OR"))) && (!IsOperator(Condition[i-1]))) orpos = i;
		}
		if(orpos == -1) {
			forup(i , 0 , ncond-1) {
				if((IsStringEqual(UpperCase(Condition[i]) , CharToString("AND"))) && (!IsOperator(Condition[i-1]))) andpos = i;
			}
			forup(i , 0 , andpos - 1) {
				condLeft[i] = Condition[i];
				ncondLeft++;
			}
			forup(i , andpos + 1 , ncond - 1) {
				condRight[ncondRight] = Condition[i];
				ncondRight++;
			}
			return isStudentRowValid(condLeft , ncondLeft , student) && isStudentRowValid(condRight , ncondRight , student);
		}
		else {
			forup(i , 0 , orpos - 1) {
				condLeft[i] = Condition[i];
				ncondLeft++;
			}
			forup(i , orpos + 1 , ncond - 1) {
				condRight[ncondRight] = Condition[i];
				ncondRight++;
			}
			return isStudentRowValid(condLeft , ncondLeft , student) || isStudentRowValid(condRight , ncondRight , student);
		}
	}
}

boolean IsLectureRowValid(string Condition[3] , TLecture lecture) {
	//KAMUS LOKAL
	
	//ALGORITMA : Mengecek semua kemungkinan kondisi pada Matakuliah,
	//jika sama, maka menghasilkan nilai true, jika tidak, false
	if(IsStringEqual(UpperCase(Condition[0]) , CharToString("KODE"))) {
		if(IsStringEqual(Condition[1] , CharToString("="))) return IsStringEqual(UpperCase(Condition[2]) , UpperCase(lecture.Kode));
		else if(IsStringEqual(Condition[1] , CharToString("!="))) return !IsStringEqual(UpperCase(Condition[2]) , UpperCase(lecture.Kode));
	}
	else if(IsStringEqual(UpperCase(Condition[0]) , CharToString("NAMA"))) {
		if(IsStringEqual(Condition[1] , CharToString("="))) return IsStringEqual(UpperCase(Condition[2]) , UpperCase(lecture.Nama));
		else if(IsStringEqual(Condition[1] , CharToString("!="))) return !IsStringEqual(UpperCase(Condition[2]) , UpperCase(lecture.Nama));
	}
	else if(IsStringEqual(UpperCase(Condition[0]) , CharToString("BIDANG"))) {
		if(IsStringEqual(Condition[1] , CharToString("="))) return IsStringEqual(UpperCase(Condition[2]) , UpperCase(lecture.Bidang));
		else if(IsStringEqual(Condition[1] , CharToString("!="))) return !IsStringEqual(UpperCase(Condition[2]) , UpperCase(lecture.Bidang));
	}
	else if(IsStringEqual(UpperCase(Condition[0]) , CharToString("SKS"))) {
		if(IsStringEqual(Condition[1] , CharToString("="))) return lecture.SKS==(int)StringToFloat(Condition[2]);
		else if(IsStringEqual(Condition[1] , CharToString("<="))) return lecture.SKS<=(int)StringToFloat(Condition[2]);
		else if(IsStringEqual(Condition[1] , CharToString(">="))) return lecture.SKS>=(int)StringToFloat(Condition[2]);
		else if(IsStringEqual(Condition[1] , CharToString("<"))) return lecture.SKS<(int)StringToFloat(Condition[2]);
		else if(IsStringEqual(Condition[1] , CharToString(">"))) return lecture.SKS>(int)StringToFloat(Condition[2]);
		else if(IsStringEqual(Condition[1] , CharToString("!="))) return lecture.SKS!=(int)StringToFloat(Condition[2]);
	}
}

boolean isLectureRowValid(string Condition[21] , int ncond , TLecture lecture) {
	//KAMUS LOKAL
	int i;
	int orpos = -1 , andpos = -1;
	string condLeft[21] , condRight[21];
	int ncondLeft = 0 , ncondRight = 0;
	
	//ALGORITMA : Mengecek semua kemungkinan kondisi pada Matakuliah
	//jika sama, maka menghasilkan nilai true, jika tidak, false
	if (ncond == 3 || ncond == 1) {
		if(IsStringEqual(UpperCase(Condition[0]) , CharToString("KODE"))) {
			if(IsStringEqual(Condition[1] , CharToString("="))) return IsStringEqual(UpperCase(Condition[2]) , UpperCase(lecture.Kode));
			else if(IsStringEqual(Condition[1] , CharToString("!="))) return !IsStringEqual(UpperCase(Condition[2]) , UpperCase(lecture.Kode));
		}
		else if(IsStringEqual(UpperCase(Condition[0]) , CharToString("NAMA"))) {
			if(IsStringEqual(Condition[1] , CharToString("="))) return IsStringEqual(UpperCase(Condition[2]) , UpperCase(lecture.Nama));
			else if(IsStringEqual(Condition[1] , CharToString("!="))) return !IsStringEqual(UpperCase(Condition[2]) , UpperCase(lecture.Nama));
		}
		else if(IsStringEqual(UpperCase(Condition[0]) , CharToString("BIDANG"))) {
			if(IsStringEqual(Condition[1] , CharToString("="))) return IsStringEqual(UpperCase(Condition[2]) , UpperCase(lecture.Bidang));
			else if(IsStringEqual(Condition[1] , CharToString("!="))) return !IsStringEqual(UpperCase(Condition[2]) , UpperCase(lecture.Bidang));
		}
		else if(IsStringEqual(UpperCase(Condition[0]) , CharToString("SKS"))) {
			if(IsStringEqual(Condition[1] , CharToString("="))) return lecture.SKS==(int)StringToFloat(Condition[2]);
			else if(IsStringEqual(Condition[1] , CharToString("<="))) return lecture.SKS<=(int)StringToFloat(Condition[2]);
			else if(IsStringEqual(Condition[1] , CharToString(">="))) return lecture.SKS>=(int)StringToFloat(Condition[2]);
			else if(IsStringEqual(Condition[1] , CharToString("<"))) return lecture.SKS<(int)StringToFloat(Condition[2]);
			else if(IsStringEqual(Condition[1] , CharToString(">"))) return lecture.SKS>(int)StringToFloat(Condition[2]);
			else if(IsStringEqual(Condition[1] , CharToString("!="))) return lecture.SKS!=(int)StringToFloat(Condition[2]);
		}
	}
	else {
		orpos = -1;
		andpos = -1;
		ncondLeft = 0;
		ncondRight = 0;
		
		forup(i , 0 , ncond-1) {
			if((IsStringEqual(UpperCase(Condition[i]) , CharToString("OR"))) && (!IsOperator(Condition[i-1]))) orpos = i;
		}
		if(orpos == -1) {
			forup(i , 0 , ncond-1) {
				if((IsStringEqual(UpperCase(Condition[i]) , CharToString("AND"))) && (!IsOperator(Condition[i-1]))) andpos = i;
			}
			forup(i , 0 , andpos - 1) {
				condLeft[i] = Condition[i];
				ncondLeft++;
			}
			forup(i , andpos + 1 , ncond - 1) {
				condRight[ncondRight] = Condition[i];
				ncondRight++;
			}
			return isLectureRowValid(condLeft , ncondLeft , lecture) && isLectureRowValid(condRight , ncondRight , lecture);
		}
		else {
			forup(i , 0 , orpos - 1) {
				condLeft[i] = Condition[i];
				ncondLeft++;
			}
			forup(i , orpos + 1 , ncond - 1) {
				condRight[ncondRight] = Condition[i];
				ncondRight++;
			}
			return isLectureRowValid(condLeft , ncondLeft , lecture) || isLectureRowValid(condRight , ncondRight , lecture);
		}
	}
}

boolean IsLecture_StudentRowValid(string Condition[3] , TLectures_Students lecture_student) {
	//KAMUS LOKAL
	
	//ALGORITMA : Mengecek semua kemungkinan kondisi pada PengambilanMK,
	//jika sama, maka menghasilkan nilai true, jika tidak, false
	if(IsStringEqual(UpperCase(Condition[0]) , CharToString("NIM"))) {
		if(IsStringEqual(Condition[1] , CharToString("="))) return IsStringEqual(Condition[2] , lecture_student.NIM);
		else if(IsStringEqual(Condition[1] , CharToString("<="))) return IsStringEqual(Condition[2] , lecture_student.NIM)||IsStringLt(lecture_student.NIM , Condition[2]);
		else if(IsStringEqual(Condition[1] , CharToString(">="))) return IsStringEqual(Condition[2] , lecture_student.NIM)||IsStringLt(Condition[2] , lecture_student.NIM);
		else if(IsStringEqual(Condition[1] , CharToString("<"))) return IsStringLt(Condition[2] , lecture_student.NIM);
		else if(IsStringEqual(Condition[1] , CharToString(">"))) return !IsStringLt(Condition[2] , lecture_student.NIM);
		else if(IsStringEqual(Condition[1] , CharToString("!="))) return !IsStringEqual(Condition[2] , lecture_student.NIM);
	}
	else if(IsStringEqual(UpperCase(Condition[0]) , CharToString("KODE"))) {
		if(IsStringEqual(Condition[1] , CharToString("="))) return IsStringEqual(UpperCase(Condition[2]) , UpperCase(lecture_student.Kode));
		else if(IsStringEqual(Condition[1] , CharToString("!="))) return !IsStringEqual(UpperCase(Condition[2]) , UpperCase(lecture_student.Kode));
	}
	else if(IsStringEqual(UpperCase(Condition[0]) , CharToString("SEMESTER"))) {
		if(IsStringEqual(Condition[1] , CharToString("="))) return lecture_student.Semester==(int)StringToFloat(Condition[2]);
		else if(IsStringEqual(Condition[1] , CharToString("<="))) return lecture_student.Semester<=(int)StringToFloat(Condition[2]);
		else if(IsStringEqual(Condition[1] , CharToString(">="))) return lecture_student.Semester>=(int)StringToFloat(Condition[2]);
		else if(IsStringEqual(Condition[1] , CharToString("<"))) return lecture_student.Semester<(int)StringToFloat(Condition[2]);
		else if(IsStringEqual(Condition[1] , CharToString(">"))) return lecture_student.Semester>(int)StringToFloat(Condition[2]);
		else if(IsStringEqual(Condition[1] , CharToString("!="))) return lecture_student.Semester!=(int)StringToFloat(Condition[2]);
	}
	else if(IsStringEqual(UpperCase(Condition[0]) , CharToString("THNAKADEMIK"))) {
		if(IsStringEqual(Condition[1] , CharToString("="))) return IsThnAkademikEqual(StringToThnAkademik(Condition[2]) , lecture_student.ThnAkademik);
		else if(IsStringEqual(Condition[1] , CharToString("<="))) return IsThnAkademikEqual(StringToThnAkademik(Condition[2]) , lecture_student.ThnAkademik)||IsThnAkademikLt(lecture_student.ThnAkademik , StringToThnAkademik(Condition[2]));
		else if(IsStringEqual(Condition[1] , CharToString(">="))) return IsThnAkademikEqual(StringToThnAkademik(Condition[2]) , lecture_student.ThnAkademik)||IsThnAkademikLt(StringToThnAkademik(Condition[2]) , lecture_student.ThnAkademik);
		else if(IsStringEqual(Condition[1] , CharToString("<"))) return IsThnAkademikLt(StringToThnAkademik(Condition[2]) , lecture_student.ThnAkademik);
		else if(IsStringEqual(Condition[1] , CharToString(">"))) return !IsThnAkademikLt(StringToThnAkademik(Condition[2]) , lecture_student.ThnAkademik);
		else if(IsStringEqual(Condition[1] , CharToString("!="))) return !IsThnAkademikEqual(StringToThnAkademik(Condition[2]) , lecture_student.ThnAkademik);
	}
	else if(IsStringEqual(UpperCase(Condition[0]) , CharToString("NILAI"))) {
		if(IsStringEqual(Condition[1] , CharToString("="))) return Condition[2].s[0]==lecture_student.Nilai;
		else if(IsStringEqual(Condition[1] , CharToString("<="))) return Condition[2].s[0]<=lecture_student.Nilai;
		else if(IsStringEqual(Condition[1] , CharToString(">="))) return Condition[2].s[0]>=lecture_student.Nilai;
		else if(IsStringEqual(Condition[1] , CharToString("<"))) return Condition[2].s[0]<lecture_student.Nilai;
		else if(IsStringEqual(Condition[1] , CharToString(">"))) return Condition[2].s[0]>lecture_student.Nilai;
		else if(IsStringEqual(Condition[1] , CharToString("!="))) return Condition[2].s[0]!=lecture_student.Nilai;
	}
}

boolean isLecture_StudentRowValid(string Condition[21] , int ncond , TLectures_Students lecture_student) {
	//KAMUS LOKAL
	int i;
	int orpos = -1 , andpos = -1;
	string condLeft[21] , condRight[21];
	int ncondLeft = 0 , ncondRight = 0;
	
	//ALGORITMA : Mengecek semua kemungkinan kondisi pada PengambilanMK,
	//jika sama, maka menghasilkan nilai true, jika tidak, false
	if (ncond == 3 || ncond == 1) {
		if(IsStringEqual(UpperCase(Condition[0]) , CharToString("NIM"))) {
			if(IsStringEqual(Condition[1] , CharToString("="))) return IsStringEqual(Condition[2] , lecture_student.NIM);
			else if(IsStringEqual(Condition[1] , CharToString("<="))) return IsStringEqual(Condition[2] , lecture_student.NIM)||IsStringLt(lecture_student.NIM , Condition[2]);
			else if(IsStringEqual(Condition[1] , CharToString(">="))) return IsStringEqual(Condition[2] , lecture_student.NIM)||IsStringLt(Condition[2] , lecture_student.NIM);
			else if(IsStringEqual(Condition[1] , CharToString("<"))) return IsStringLt(Condition[2] , lecture_student.NIM);
			else if(IsStringEqual(Condition[1] , CharToString(">"))) return !IsStringLt(Condition[2] , lecture_student.NIM);
			else if(IsStringEqual(Condition[1] , CharToString("!="))) return !IsStringEqual(Condition[2] , lecture_student.NIM);
		}
		else if(IsStringEqual(UpperCase(Condition[0]) , CharToString("KODE"))) {
			if(IsStringEqual(Condition[1] , CharToString("="))) return IsStringEqual(UpperCase(Condition[2]) , UpperCase(lecture_student.Kode));
			else if(IsStringEqual(Condition[1] , CharToString("!="))) return !IsStringEqual(UpperCase(Condition[2]) , UpperCase(lecture_student.Kode));
		}
		else if(IsStringEqual(UpperCase(Condition[0]) , CharToString("SEMESTER"))) {
			if(IsStringEqual(Condition[1] , CharToString("="))) return lecture_student.Semester==(int)StringToFloat(Condition[2]);
			else if(IsStringEqual(Condition[1] , CharToString("<="))) return lecture_student.Semester<=(int)StringToFloat(Condition[2]);
			else if(IsStringEqual(Condition[1] , CharToString(">="))) return lecture_student.Semester>=(int)StringToFloat(Condition[2]);
			else if(IsStringEqual(Condition[1] , CharToString("<"))) return lecture_student.Semester<(int)StringToFloat(Condition[2]);
			else if(IsStringEqual(Condition[1] , CharToString(">"))) return lecture_student.Semester>(int)StringToFloat(Condition[2]);
			else if(IsStringEqual(Condition[1] , CharToString("!="))) return lecture_student.Semester!=(int)StringToFloat(Condition[2]);
		}
		else if(IsStringEqual(UpperCase(Condition[0]) , CharToString("THNAKADEMIK"))) {
			if(IsStringEqual(Condition[1] , CharToString("="))) return IsThnAkademikEqual(StringToThnAkademik(Condition[2]) , lecture_student.ThnAkademik);
			else if(IsStringEqual(Condition[1] , CharToString("<="))) return IsThnAkademikEqual(StringToThnAkademik(Condition[2]) , lecture_student.ThnAkademik)||IsThnAkademikLt(lecture_student.ThnAkademik , StringToThnAkademik(Condition[2]));
			else if(IsStringEqual(Condition[1] , CharToString(">="))) return IsThnAkademikEqual(StringToThnAkademik(Condition[2]) , lecture_student.ThnAkademik)||IsThnAkademikLt(StringToThnAkademik(Condition[2]) , lecture_student.ThnAkademik);
			else if(IsStringEqual(Condition[1] , CharToString("<"))) return IsThnAkademikLt(StringToThnAkademik(Condition[2]) , lecture_student.ThnAkademik);
			else if(IsStringEqual(Condition[1] , CharToString(">"))) return !IsThnAkademikLt(StringToThnAkademik(Condition[2]) , lecture_student.ThnAkademik);
			else if(IsStringEqual(Condition[1] , CharToString("!="))) return !IsThnAkademikEqual(StringToThnAkademik(Condition[2]) , lecture_student.ThnAkademik);
		}
		else if(IsStringEqual(UpperCase(Condition[0]) , CharToString("NILAI"))) {
			if(IsStringEqual(Condition[1] , CharToString("="))) return Condition[2].s[0]==lecture_student.Nilai;
			else if(IsStringEqual(Condition[1] , CharToString("<="))) return Condition[2].s[0]<=lecture_student.Nilai;
			else if(IsStringEqual(Condition[1] , CharToString(">="))) return Condition[2].s[0]>=lecture_student.Nilai;
			else if(IsStringEqual(Condition[1] , CharToString("<"))) return Condition[2].s[0]<lecture_student.Nilai;
			else if(IsStringEqual(Condition[1] , CharToString(">"))) return Condition[2].s[0]>lecture_student.Nilai;
			else if(IsStringEqual(Condition[1] , CharToString("!="))) return Condition[2].s[0]!=lecture_student.Nilai;
		}
	}
	else {
		orpos = -1;
		andpos = -1;
		ncondLeft = 0;
		ncondRight = 0;
		
		forup(i , 0 , ncond-1) {
			if((IsStringEqual(UpperCase(Condition[i]) , CharToString("OR"))) && (!IsOperator(Condition[i-1]))) orpos = i;
		}
		if(orpos == -1) {
			forup(i , 0 , ncond-1) {
				if((IsStringEqual(UpperCase(Condition[i]) , CharToString("AND"))) && (!IsOperator(Condition[i-1]))) andpos = i;
			}
			forup(i , 0 , andpos - 1) {
				condLeft[i] = Condition[i];
				ncondLeft++;
			}
			forup(i , andpos + 1 , ncond - 1) {
				condRight[ncondRight] = Condition[i];
				ncondRight++;
			}
			return isLecture_StudentRowValid(condLeft , ncondLeft , lecture_student) && isLecture_StudentRowValid(condRight , ncondRight , lecture_student);
		}
		else {
			forup(i , 0 , orpos - 1) {
				condLeft[i] = Condition[i];
				ncondLeft++;
			}
			forup(i , orpos + 1 , ncond - 1) {
				condRight[ncondRight] = Condition[i];
				ncondRight++;
			}
			return isLecture_StudentRowValid(condLeft , ncondLeft , lecture_student) || isLecture_StudentRowValid(condRight , ncondRight , lecture_student);
		}
	}
}

//OPERASI PADA TAHUN AKADEMIK
boolean IsThnAkademikEqual(TAcademicYear thn1 , TAcademicYear thn2) {
	//KAMUS LOKAL
	
	//ALGORITMA
	return (thn1.Start==thn2.Start)&&(thn1.End==thn2.End);
}

boolean IsThnAkademikLt(TAcademicYear thn1 , TAcademicYear thn2) {
	//KAMUS LOKAL
	
	//ALGORITMA
	return thn1.Start<thn2.Start;
}	

TAcademicYear StringToThnAkademik(string S) {
	//KAMUS LOKAL
	TAcademicYear thn;
	
	//ALGORITMA
	sscanf(S.s , "%d-%d" , &thn.Start , &thn.End);
	return thn;
}

string ThnAkademikToString(TAcademicYear thn) {
	//KAMUS LOKAL
	string s;
	
	//ALGORITMA
	sprintf(s.s , "%d-%d" , thn.Start , thn.End);
	return CharToString(s.s);
}

//OPERASI LAIN
int GetSizeStudent(TStudent student) {
	//KAMUS LOKAL
	int ipk = 0 , jmlsks = 0;
	
	//ALGORITMA : Menjumlahkan semua ukuran bagian dari record Mahasiswa
	if(student.IPK!=null) ipk=2;
	if(student.JumlahSKS!=null) jmlsks=2;
	return student.NIM.length+student.Nama.length+student.KotaAsal.length+6+ipk+jmlsks;
}

int GetSizeLecture(TLecture lecture) {
	//KAMUS LOKAL
	
	//ALGORITMA : Menjumlahkan semua ukuran bagian dari record Matakuliah
	if(lecture.SKS!=null) return lecture.Kode.length+lecture.Nama.length+lecture.Bidang.length+2;
	else return lecture.Kode.length+lecture.Nama.length+lecture.Bidang.length;
}

int GetSizeLecture_Student(TLectures_Students lecture_student) {
	//KAMUS LOKAL
	
	//ALGORITMA : Menjumlahkan semua ukuran bagian dari record PengambilanMK
	if(lecture_student.Nilai=='-') return lecture_student.NIM.length+lecture_student.Kode.length+2+4;
	else return lecture_student.NIM.length+lecture_student.Kode.length+2+1+4;
}

void Synchronize(TNodeList *NodeList , TAdjMatrix *m , TNode Asal) {
	//KAMUS LOKAL
	int i , j , k , l;
	TRetvalDijkstra x;
	TTabstudents TempTable;
	TTablectures TempTable2;
	TTablectures_students TempTable3;
	
	//ALGORITMA 
	//delete data mahasiswa yang tidak valid
	TempTable = MergeTabStudent(NodeList);
	forup(i , 1 , NodeList->NNode) {
		j = 1;
		x = FindPath(*m , 0.001 , NodeList->NNode , GetPhysicalNodeName(NodeList , Asal.Name) , GetPhysicalNodeName(NodeList , NodeList->node[i].Name) , 100);
		if(x.PathLength != 0) {
			while(j <= NodeList->node[i].lectures_students.NRelation) {
				if(!SearchStudent(&TempTable , NodeList->node[i].lectures_students.t[j].NIM)) {
					int k;
					forup(k , j , NodeList->node[i].lectures_students.NRelation-1) {
					NodeList->node[i].lectures_students.t[k]=NodeList->node[i].lectures_students.t[k+1];
					}
					CreateEmptyRelation(&NodeList->node[i].lectures_students.t[NodeList->node[i].lectures_students.NRelation]);
					NodeList->node[i].lectures_students.NRelation--;
				}
				else j++;
			}
		}
	}
	
	//delete data kuliah yang tidak valid
	TempTable2 = MergeTabLecture(NodeList);
	forup(i , 1 , NodeList->NNode) {
		j = 1;
		x = FindPath(*m , 0.001 , NodeList->NNode , GetPhysicalNodeName(NodeList , Asal.Name) , GetPhysicalNodeName(NodeList , NodeList->node[i].Name) , 100);
		if(x.PathLength != 0) {
			while(j <= NodeList->node[i].lectures_students.NRelation) {
				if(!SearchLecture(&TempTable2 , NodeList->node[i].lectures_students.t[j].Kode)) {
					int k;
					forup(k , j , NodeList->node[i].lectures_students.NRelation-1) {
					NodeList->node[i].lectures_students.t[k]=NodeList->node[i].lectures_students.t[k+1];
					}
					CreateEmptyRelation(&NodeList->node[i].lectures_students.t[NodeList->node[i].lectures_students.NRelation]);
					NodeList->node[i].lectures_students.NRelation--;
				}
				else j++;
			}
		}
	}
	
	//Update IPK dan JumlahSKS	
	TempTable3 = MergeTabRelation(NodeList);
	forup(i , 1 , NodeList->NNode) {
		forup(j , 1 , NodeList->node[i].students.NStudents) {
			int jumlahsks = 0;
			float jumlahnilai = 0;
			boolean found = false;
			forup(k , 1 , TempTable3.NRelation) {
				if(IsStringEqual(TempTable3.t[k].NIM , NodeList->node[i].students.t[j].NIM)) {
					forup(l , 1 , TempTable2.NLectures) {
						if(IsStringEqual(TempTable2.t[l].Kode , TempTable3.t[k].Kode)) {
							jumlahsks += TempTable2.t[l].SKS;
							jumlahnilai += (float)(4 - (TempTable3.t[k].Nilai - 'A'))* (float)TempTable2.t[l].SKS;
						}
					}
					found = true;
				}
			}
			if(found) {
				NodeList->node[i].students.t[j].JumlahSKS = jumlahsks;
				NodeList->node[i].students.t[j].IPK = jumlahnilai / (float)jumlahsks;
			}
			else {
				NodeList->node[i].students.t[j].JumlahSKS = -1;
				NodeList->node[i].students.t[j].IPK = -1;
			}
		}
	}
}
